package com.zdxf.client.controller;

import com.zdxf.client.domain.SystemInfoDO;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.OperatingSystem;
import oshi.util.FormatUtil;

import java.io.File;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class System {

    static void printlnCpuInfo(SystemInfoDO res) throws InterruptedException {
        SystemInfo systemInfo = new SystemInfo();
        CentralProcessor processor = systemInfo.getHardware().getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        // 睡眠1s
        TimeUnit.SECONDS.sleep(1);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
        int cpuCount = processor.getLogicalProcessorCount();
        double systemCpuLoad = cSys * 1.0 / totalCpu;
        double userCpuLoad = user * 1.0 / totalCpu;
        double iowaitCpuLoad = iowait * 1.0 / totalCpu;
        double idleCpuLoad = 1.0 - idle * 1.0 / totalCpu;
        res.setCpuCount(cpuCount);
        res.setSystemCpuLoad(systemCpuLoad);
        res.setUserCpuLoad(userCpuLoad);
        res.setIowaitCpuLoad(iowaitCpuLoad);
        res.setIdleCpuLoad(idleCpuLoad);
        res.setSystemCpuLoadStr(new DecimalFormat("#.##%").format(systemCpuLoad));
        res.setUserCpuLoadStr(new DecimalFormat("#.##%").format(userCpuLoad));
        res.setIowaitCpuLoadStr(new DecimalFormat("#.##%").format(iowaitCpuLoad));
        res.setIdleCpuLoadStr(new DecimalFormat("#.##%").format(idleCpuLoad));
    }

    public static void OperatingInfo(SystemInfoDO res)  {
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();
        res.setProcessCount(os.getProcessCount());
        res.setThreadCount(os.getThreadCount());
    }

    public static void CpuLoadInfo(SystemInfoDO res)  {
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        CentralProcessor processor = hal.getProcessor();
        double[] loadAverage = processor.getSystemLoadAverage(3);
        res.setCpuLoad1(loadAverage[0] < 0 ? 0 : loadAverage[0]);
        res.setCpuLoad5(loadAverage[1] < 0 ? 0 : loadAverage[1]);
        res.setCpuLoad15(loadAverage[2] < 0 ? 0 : loadAverage[2]);
    }

    public static void NetInfo(SystemInfoDO res) throws InterruptedException {
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        List<NetworkIF> networkIFs = hal.getNetworkIFs();
        long Recv1 = 0;
        long Sent1 = 0;
        long Recv2 = 0;
        long Sent2 = 0;
        for (NetworkIF net : networkIFs) {
            Recv1 += net.getBytesRecv() > 0 ? net.getBytesRecv() : 0;
            Sent1 += net.getBytesSent() > 0 ? net.getBytesSent() : 0;
        }
        TimeUnit.SECONDS.sleep(1);
        si = new SystemInfo();
        hal = si.getHardware();
        networkIFs = hal.getNetworkIFs();
        for (NetworkIF net : networkIFs) {
            Recv2 += net.getBytesRecv() > 0 ? net.getBytesRecv() : 0;
            Sent2 += net.getBytesSent() > 0 ? net.getBytesSent() : 0;
        }
        res.setNetRecv(Recv2 - Recv1);
        res.setNetSent(Sent2 - Sent1);
        res.setNetSentStr(formatNumber((Sent2 - Sent1)
                / (float) (1024 * 1024)));
        res.setNetRecvStr(formatNumber((Recv2 - Recv1)
                / (float) (1024 * 1024)));
    }

    public static void MemInfo(SystemInfoDO res) {
        SystemInfo systemInfo = new SystemInfo();
        GlobalMemory memory = systemInfo.getHardware().getMemory();
        //总内存
        long totalByte = memory.getTotal();
        //剩余
        long availableByte = memory.getAvailable();
        res.setMemoryTotal(totalByte);//操作系统总物理内存
        res.setMemoryFree(availableByte);//操作系统物理剩余内存
        res.setMemoryUse(totalByte - availableByte);//操作系统物理内存使用
        res.setMemoryTotalStr(FormatUtil.formatBytes(totalByte));
        res.setMemoryFreeStr(FormatUtil.formatBytes(availableByte));
        res.setMemoryUseStr(FormatUtil.formatBytes(totalByte - availableByte));
    }

    public static void DiskInfo(SystemInfoDO res) {
        File[] disks = File.listRoots();
        long disksTotal = 0;
        long disksUse = 0;
        long disksFree = 0;
        for (File file : disks) {
            disksTotal += file.getTotalSpace();
            disksUse += file.getTotalSpace() - file.getUsableSpace();
            disksFree += file.getFreeSpace();
        }
        res.setDisksTotal(disksTotal);
        res.setDisksUse(disksUse);
        res.setDisksFree(disksFree);
        res.setDisksTotalStr(FormatUtil.formatBytes(disksTotal));
        res.setDisksFreeStr(FormatUtil.formatBytes(disksFree));
        res.setDisksUseStr(FormatUtil.formatBytes(disksUse));
    }
    public static  void getWinDiskUsage(SystemInfoDO res) {
        SystemInfo systemInfo = new SystemInfo();
        HardwareAbstractionLayer hal = systemInfo.getHardware();
        HWDiskStore[] diskStores = hal.getDiskStores().toArray(new HWDiskStore[0]);
        long total = 0;
        long used = 0;
        if (diskStores != null && diskStores.length > 0) {
            for (HWDiskStore diskStore : diskStores) {
                long size = diskStore.getSize();
                long writeBytes = diskStore.getWriteBytes();
                total += size;
                used += writeBytes;
            }
        }
        res.setDisksTotal(total);
        res.setDisksUse(used);
        res.setDisksFree(total-used);
        res.setDisksTotalStr(FormatUtil.formatBytes(total));
        res.setDisksFreeStr(FormatUtil.formatBytes(total-used));
        res.setDisksUseStr(FormatUtil.formatBytes(used));
    }

    public static void setSysInfo(SystemInfoDO res) {
        Properties props = java.lang.System.getProperties();
        //系统名称
        String osName = props.getProperty("os.name");
        //架构名称
        String osArch = props.getProperty("os.arch");
        res.setOsName(osName);//操作系统的版本
        res.setOsArch(osArch);//系统架构
    }

    public static void getAllInfo(SystemInfoDO res) throws InterruptedException {
        getWinDiskUsage(res);
        setSysInfo(res);
        MemInfo(res);
        printlnCpuInfo(res);
    }
    private static String formatNumber(Object obj) {
        String result = "";
        if (obj.getClass().getSimpleName().equals("Float")) {
            result = new Formatter().format("%.2f", (float) obj).toString();
        } else if (obj.getClass().getSimpleName().equals("Double")) {
            result = new Formatter().format("%.2f", (double) obj).toString();
        }
        return result;
    }

}
